/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.isd.pool.web;

import com.isd.facturacion.modelo.MovimientoTienda;
import com.isd.global.excepciones.RollbackFailureException;
import com.isd.global.modelo.CorreoElectronico;
import com.isd.global.modelo.Parametro;
import com.isd.global.rn.ParametrosRN;
import com.isd.global.util.JsfUtil;
import com.isd.global.util.SenderEmail;
import com.isd.global.web.MailFactory;
import com.isd.pool.modelo.CondicionesPagoPool;
import com.isd.pool.modelo.EstadoPool;
import com.isd.pool.modelo.EstadoReserva;
import com.isd.pool.modelo.ItemProductoPool;
import com.isd.pool.modelo.ItemReserva;
import com.isd.pool.modelo.Pool;
import com.isd.pool.modelo.ReservasPool;
import com.isd.pool.rn.PoolRN;
import com.isd.seguridad.web.UsuarioSessionBean;
import com.isd.ventas.rn.LimiteCreditoVentaRN;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import org.primefaces.event.FlowEvent;

/**
 * Beans para comprar pooles seleccionados
 * @author ctrosch
 */
@ManagedBean
@ViewScoped
public class PoolSessionBean implements Serializable{

    @EJB private ParametrosRN parametroRN;
    @EJB private LimiteCreditoVentaRN limiteCreditoVentaRN;
    @EJB private PoolRN poolRN;

    Parametro p;
    Integer porCantidad;

    private CondicionesPagoPool condicionPago;
    private List<CondicionesPagoPool> condicionesDisponibles;

    private boolean soloContado;
    private boolean compraConfirmada;

    private Pool pool;
    private MovimientoTienda pedido;
    private String idPool;
    private ReservasPool reserva;

    @ManagedProperty(value = "#{usuarioSessionBean}")
    private UsuarioSessionBean usuarioSession;

    @ManagedProperty(value = "#{poolAplicacionBean}")
    private PoolAplicacionBean poolAplicacionBean;

    @EJB private MailFactory mailFactoryBean;

    /** Creates a new instance of PoolBean */
    public PoolSessionBean() {

    }

    @PostConstruct
    private void init() {
      
        try {
            
            p = parametroRN.getParametros();
            condicionesDisponibles = new ArrayList<CondicionesPagoPool>();
            resetParametros();

        } catch (Exception ex) {

        }
    }

    public void cargarPool(){

        try {
            if (idPool != null) {
                
                pool = poolRN.getPool(idPool);                
                condicionesDisponibles = pool.getCondiconesDePago();
                resetParametros();
                
                if (pool == null) {
                    JsfUtil.addErrorMessage("No se encontró venta especial");
                }
                
                if (!usuarioSession.isEstaRegistrado()) {
                    JsfUtil.addInfoMessage("Ingrese usuario y clave para identificarse, luego haga click en \"Ingresar\" ");
                }
            }
            idPool = null;
        } catch (Exception e) {
            idPool = null;
        }
    }

    public String seleccionarPool(Pool p){

        pool = p;
        condicionesDisponibles = pool.getCondiconesDePago();
        resetParametros();
        
        if(!usuarioSession.isEstaRegistrado()){
            JsfUtil.addInfoMessage("Ingrese usuario y clave para identificarse, luego haga click en \"Ingresar\" ");
        }
        return "../pool/pool.xhtml";       
    }

    public void seleccionarCondicionPago(CondicionesPagoPool c){
        
        condicionPago = c;        
    }

    public void resetParametros(){

        compraConfirmada = false;
        condicionPago = null;

        if(usuarioSession.isEstaRegistrado() && usuarioSession.getUsuario().getCliente()!=null){
            cargarCondicionesDePago();
        }
    }

    public String onFlowProcess(FlowEvent event) {

        if(usuarioSession.isEstaRegistrado()){
            
            if(usuarioSession.getUsuario().getTipo() == 'V' && usuarioSession.getUsuario().getCliente()==null ){

                JsfUtil.addErrorMessage("Seleccione un cliente y vuelva a intentar");
                return event.getOldStep();
            }

            if(usuarioSession.getUsuario().getCliente() != null){
                if(usuarioSession.getUsuario().getCliente().getBloqueadoEnPool().equals("S")){
                    JsfUtil.addWarningMessage("Cliente no habilitado para ventas especiales");
                    return event.getOldStep();
                }
            }
        }else{

            JsfUtil.addWarningMessage("Debe estar registrado para continuar");
            JsfUtil.addInfoMessage("Ingrese usuario y clave para identificarse, luego haga click en \"Ingresar\" ");
            return event.getOldStep();
        }

        if(pool==null || !pool.isActiva()){
            JsfUtil.addWarningMessage("La venta seleccionada especial ya no está disponible");
            return event.getOldStep();
        }

        if(!pool.getEstado().equals(EstadoPool.Activo)){
            JsfUtil.addWarningMessage("La venta especiál seleccionada ya no está activa");
            return event.getOldStep();
        }
        
        if(event.getNewStep().equals("condicionPago")){
            JsfUtil.addInfoMessage("Seleccione una condición de pago");
        }

        if(event.getOldStep().equals("condicionPago") && event.getNewStep().equals("cantidades")){

            if(!generarReserva()){
               return event.getOldStep();
            }
            JsfUtil.addInfoMessage("Ingrese las cantidades a comprar");
            return "cantidades";            
        }

        if(event.getOldStep().equals("cantidades") && event.getNewStep().equals("confirmacion")){

            if(!validarCantidades()){
                return event.getOldStep();
            }
        }

        if(event.getNewStep().equals("confirmacion")){

            JsfUtil.addInfoMessage("Ha llegado al final, haga click en \"Confirmar reserva\" para finalizar");
        }

        if(event.getOldStep().equals("confirmacion") && event.getNewStep().equals("cantidades") && compraConfirmada){
            JsfUtil.addWarningMessage("Su reserva ha sido confirmada, no puede volver al paso anterior");
            return event.getOldStep();
        }

        return event.getNewStep();
    }

    public void login(){
        
        String sLogin = usuarioSession.login();
        resetParametros();
    }

    public boolean validarCantidades(){

        boolean todoOk = true;
        BigDecimal cantTotal = BigDecimal.ZERO;

        if(reserva.getItemReservas()==null){
            JsfUtil.addErrorMessage("Error, no es posible validar las cantidades");
            todoOk = false;
        }

//        //if(reserva.getCantidad().compareTo(pool.getCantidadDisponible())== 1){
//            JsfUtil.addWarningMessage("Lo sentimos!, no existen cantidades disponible para la venta especial seleccionada. Muchas gracias por participar");
//            todoOk = false;
//        }        

        //Controlamos las cantidades por items
        for(ItemReserva ir: reserva.getItemReservas()){
            
            //Verificamos las cantidades disponibles a nivel de items
            for(ItemProductoPool ipp: pool.getProductos()){            
                if(ipp.getProducto().equals(ir.getProducto()) && (ir.getCantidad().compareTo(ipp.getCantidadDisponible())== 1) ){                    
                    
                    if(ipp.getCantidadDisponible().intValue()>0){
                        JsfUtil.addWarningMessage("Lo sentimos!, quedan "+ipp.getCantidadDisponible().intValue()+" cantidades disponibles para "+ipp.getProducto().getDescrp() );    
                    }else{
                        JsfUtil.addWarningMessage("Lo sentimos!, queda "+ipp.getCantidadDisponible().intValue()+" cantidade disponibles para "+ipp.getProducto().getDescrp() );
                    }                    
                    
                    todoOk = false;                    
                    break;
                }                    
            }
            
            if(ir.getCantidad()!=null){
                cantTotal = cantTotal.add(ir.getCantidad());
            }

            if(ir.getCantidadMinima().compareTo(BigDecimal.ZERO)!= 0 && ir.getCantidad().compareTo(ir.getCantidadMinima())== -1 ){
                JsfUtil.addWarningMessage("La cantidad mínima de compra para " + ir.getProducto().getDescrp()
                        + " es "+ ir.getCantidadMinima().intValue()+", ingrese un valor mayor");
                todoOk = false;
                break;
            }

            if(ir.getCantidadMaxima().compareTo(BigDecimal.ZERO)!= 0 && ir.getCantidad().compareTo(ir.getCantidadMaxima())== 1 ){
                JsfUtil.addWarningMessage("La cantidad máxima de compra para " + ir.getProducto().getDescrp()
                        + " es "+ ir.getCantidadMaxima().intValue()+", ingrese un valor menor");
                todoOk = false;
                break;
            }
        }
        
        if(cantTotal.compareTo(BigDecimal.ONE)==-1){
            JsfUtil.addWarningMessage("Ingrese un valor válido, mayor a cero.");
            todoOk = false;
        }

        if(pool.getCantidadMinimaTotal().compareTo(BigDecimal.ZERO)!= 0 && cantTotal.compareTo(pool.getCantidadMinimaTotal())== -1 ){
            JsfUtil.addWarningMessage("La cantidad mínima total de compra es "+ pool.getCantidadMinimaTotal().intValue()+", ingrese un valor mayor");
            todoOk = false;
        }

        if(pool.getCantidadMaximaTotal().compareTo(BigDecimal.ZERO)!= 0 && cantTotal.compareTo(pool.getCantidadMaximaTotal())== 1 ){
            JsfUtil.addWarningMessage("La cantidad máxima total de compra es "+ pool.getCantidadMaximaTotal().intValue()+", ingrese un valor menor");
            todoOk = false;
        }

        return todoOk;
    }

    public boolean generarReserva(){
        
        try {
            if(usuarioSession.getUsuario().getCliente()==null){
                JsfUtil.addErrorMessage("No existe un cliente asignado para generar la reserva");
                return false;
            }

            if(condicionPago==null){
                JsfUtil.addErrorMessage("Seleccione la condición de pago");
                return false;
            }

            reserva = new ReservasPool(usuarioSession.getUsuario().getCliente().getNrocta(), pool);
            reserva.setCliente(usuarioSession.getUsuario().getCliente());
            reserva.setCondicionDePago(condicionPago.getCondicionDePago());

            for (ItemProductoPool ipp : pool.getProductos()) {

                ItemReserva ir = new ItemReserva(reserva, ipp.getProducto());
                ir.setCantidadMinima(ipp.getCantidadMinima());
                ir.setCantidadMaxima(ipp.getCantidadMaxima());
                ir.setPrecio(condicionPago.getPrecioPool());
                ir.setCantidadDisponible(ipp.getCantidadDisponible().intValue());

                reserva.getItemReservas().add(ir);
            }
            
            return true;
            
        } catch (Exception e) {
            JsfUtil.addErrorMessage("No es posible generar la reserva");
            return false;
        }
    }

    public synchronized void confirmarReserva(){

        if(usuarioSession.isEstaRegistrado()){
            
            try {
                BigDecimal limiteDisponible = limiteCreditoVentaRN.getLimiteCreditoDisponible(reserva.getCliente());
                
                pool = poolRN.getPool(pool.getNroPool());
                
//                if(reserva.getCantidad().compareTo(pool.getCantidadDisponible())== 1){
//                    JsfUtil.addWarningMessage("Lo sentimos!, no podemos hacer su reserva, no quedan cantidades disponibles. Muchas gracias por participar");
//                    return;
//                }
                
                //Controlamos las cantidades por items
                for(ItemReserva ir: reserva.getItemReservas()){
                    //Verificamos las cantidades disponibles a nivel de items
                    for(ItemProductoPool ipp: pool.getProductos()){
                        if(ipp.getProducto().equals(ir.getProducto()) && (ir.getCantidad().compareTo(ipp.getCantidadDisponible())== 1) ){
                            JsfUtil.addWarningMessage("Lo sentimos!, no existen cantidades disponible para "+ipp.getProducto().getDescrp() + ". Muchas gracias por participar");
                            return;
                        }                    
                    }
                }
             
                //Verificación si no pasa límite de crédito
                if(reserva.getTotalReservaConIva().compareTo(limiteDisponible)==1){
                    
                }
                
                reserva.setEstado(EstadoReserva.Confirmado);                
                asignarNroOrdenReserva();                
                
                pool.getReservas().add(reserva);                                
                poolRN.guardar(pool);                
                poolAplicacionBean.sincronizarCantidades(pool);                                
                poolRN.guardar(pool);       
                poolAplicacionBean.actualizarDatos();
                compraConfirmada  = true;
                
                JsfUtil.addInfoMessage("Su reserva ha sido registrada. Le informaremos luego si esta venta especial finaliza exitosamente");                
                enviarNotificaciones();
                
            } catch (RollbackFailureException ex) {
                JsfUtil.addErrorMessage("No es posible realizar su reserva en estos momentos, disculpe las molestias");
                Logger.getLogger(PoolSessionBean.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                JsfUtil.addErrorMessage("No es posible realizar su reserva en estos momentos, disculpe las molestias");
                Logger.getLogger(PoolSessionBean.class.getName()).log(Level.SEVERE, null, ex);
            }            
        }else{            
            JsfUtil.addErrorMessage("No hay usuario registrado");
            compraConfirmada  = false;
        }
    }

    public void enviarNotificaciones(){

        List<CorreoElectronico> correos = new ArrayList<CorreoElectronico>();

        correos.add(generarCorreoElectronicoEmpresa());
        correos.add(generarCorreoElectronicoCliente());        
        //Enviamos los correos con un nuevo hilo...
        SenderEmail se = new SenderEmail(mailFactoryBean, correos);
        se.start();
    }

    public CorreoElectronico generarCorreoElectronicoEmpresa() {

        try {

            String  asunto = "Reserva "+ pool.getTipo().getDescrp()+" Nro.: "+ pool.getNroPool()+ " Confirmada!" ;
            String destinatarios = mailFactoryBean.validarDestinatario(p.getCorreoElectronicoPool(), false);
            
            destinatarios += (reserva.getCliente().getVendedor().getCamail()==null?"":";"+reserva.getCliente().getVendedor().getCamail());                            
            destinatarios += ";"+mailFactoryBean.validarDestinatario(reserva.getCliente().getSitio().getEmailPedidos(), false);            

            List<String> contenido = generarMensajeCorreoElectronico();
            contenido.set(0, "<b>Nueva reserva "+pool.getTipo().getDescrp()+" Nro.: " + pool.getNroPool() +"</b>");
            contenido.set(1, "<hr/>");
            contenido.set(2, "Cliente: " + reserva.getCliente().getNombre());
            contenido.set(11, "");
            
            return new CorreoElectronico(asunto, destinatarios, mailFactoryBean.generarMensaje("Ventas especiales",contenido));
            
        } catch (Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "generarCorreoElectronicoEmpresa", e);            
            return new CorreoElectronico("Error", "claudiotrosch@gmail.com", "Problemas para generar correo confirmación de reserva a empresa");
        }
    }

    public CorreoElectronico generarCorreoElectronicoCliente() {

        try {

            String asunto = "Reserva en "+pool.getTipo().getDescrp()+" - Nro.: "+ pool.getNroPool()+ " Confirmada!";
            String destinatario = mailFactoryBean.validarDestinatario(reserva.getCliente().getDireml(), true);

            if(destinatario.isEmpty()) {
                destinatario = mailFactoryBean.validarDestinatario(reserva.getCliente().getSitio().getEmailPedidos(),false);
                return JsfUtil.getCorreoElectronicoClienteSinCorreo(reserva.getCliente(), destinatario);
            }

            String mensaje = mailFactoryBean.generarMensaje("Ventas especiales",generarMensajeCorreoElectronico());

            return new CorreoElectronico(asunto, destinatario, mensaje);

        } catch (Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "generarCorreoElectronicoCliente", e);            
            return new CorreoElectronico("Error", "claudiotrosch@gmail.com", "Problemas para generar correo confirmación de reserva a cliente");
        }
    }

    public List<String> generarMensajeCorreoElectronico(){

        SimpleDateFormat formateadorFecha = new SimpleDateFormat("dd/MM/yyyy");
        List<String> contenido = new ArrayList<String>();

        contenido.add("<b>Estimado Cliente:</b>");
        contenido.add("Gracias por su reserva en "+pool.getTipo().getDescrp()+" - Nro.: "+pool.getNroPool()+" - "+ pool.getDescripcion());
        contenido.add("<hr/>");
        contenido.add("Fecha reserva: " + formateadorFecha.format(reserva.getFecalt()));
        contenido.add("Reserva Número: " + reserva.getOrden());
        contenido.add("Condición de pago: " + reserva.getCondicionDePago().getDescrp());
        contenido.add("Observaciones: " + (reserva.getTextos()==null ? "" : reserva.getTextos()));
        contenido.add("<hr/>");

        contenido.add("Productos reservados");
        String sItems ="";

        if(!reserva.getItemReservas().isEmpty()){

            sItems += "<table style=\"font-family: Arial, Helvetica, sans-serif; width: 700px; border: 0px solid #eeeeee;\" border=\"0\" cellspacing=\"2\" cellpadding=\"0\" align=\"center\">";
            sItems += "<tr><td><b>Cant.</b></td>"
                    + "<td align=\"center\" ><b>Descripción</b></td> "
                    + "<td align=\"right\" width=\"30\"><b>Pcio. Unit.</b></td>"
                    + "<td align=\"right\" width=\"30\" ><b>Subtotal c/IVA</b></td></tr>";

            BigDecimal totalReserva = BigDecimal.ZERO;

            for(ItemReserva i: reserva.getItemReservas()){
                    
                    sItems += "<tr><td align=\"right\" width=\"15\" >"+i.getCantidad()+"</td>";
                    sItems += "<td style=\"margin-left: 10px;\">"+i.getProducto().getDescrp().trim()+"</td>";
                    sItems += "<td align=\"right\" width=\"50\" >"+i.getPrecioFinalConIVA().setScale(2, 2)+"</td>";
                    sItems += "<td align=\"right\" width=\"50\" >"+i.getPrecioFinalConIVA().multiply(i.getCantidad()).setScale(2, 2)+"</td></tr>";                    
                
                totalReserva = totalReserva.add((i.getPrecioFinalConIVA().multiply(i.getCantidad()).setScale(2, 2)));
            }

            sItems += "<tr><td align=\"right\" colspan=\"2\"><b>Total c/IVA:</b></td><td align=\"right\"><b>$"+totalReserva+"</b></td></tr></table>";
        }

        contenido.add(sItems);
        
        UtilidadesPool.agregarBasesCondiciones(pool, contenido);
        
        contenido.add("<hr>");
        contenido.add("Muchas gracias por utilizar nuestra tienda virtual! ");

        return contenido;
    }

    public int porcentajeFinalizadoPool(Pool p){

        try {

            float d = p.getCantidadDisponible().floatValue();
            float t = p.getCantidadTotal().floatValue();
            float r = 100 - d / t * 100;

            //Si el total es igual a cero retorna cero
            if(t==0) return 0;

            //Si lo disponible es mayor al total
            if(d>t) return 0;

            //Si lo disponible es menor
            if(d<0) return 100;

            return new BigDecimal(r).intValue();

        } catch (Exception e) {

            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "porcentajeFinalizadoPool", e);            
            return 0;
        }
    }

    private void cargarCondicionesDePago(){

        boolean encontroCondiciones = false;
        condicionesDisponibles = new ArrayList<CondicionesPagoPool>();

        if(usuarioSession.getUsuario().getCliente().getPoolSoloContado().equals("S")){

            for(CondicionesPagoPool cpp: pool.getCondiconesDePago()){

                if(cpp.getCondicionDePago().getCndpag().equals("000")){

                    condicionesDisponibles.add(cpp);
                    encontroCondiciones = true;
                }
            }

            if(!encontroCondiciones){
                condicionesDisponibles = pool.getCondiconesDePago();
            }

        }else{
            condicionesDisponibles = pool.getCondiconesDePago();
        }
    }

    //------------------------------------------------------------------------------------------
    

    public Parametro getP() {
        return p;
    }

    public void setP(Parametro p) {
        this.p = p;
    }

    public Integer getPorCantidad() {

        return porCantidad;
    }

    public void setPorCantidad(Integer porCantidad) {
        this.porCantidad = porCantidad;
    }

    public boolean isCompraConfirmada() {
        return compraConfirmada;
    }

    public void setCompraConfirmada(boolean compraConfirmada) {
        this.compraConfirmada = compraConfirmada;
    }

    public CondicionesPagoPool getCondicionPago() {
        return condicionPago;
    }

    public void setCondicionPago(CondicionesPagoPool condicionPago) {
        this.condicionPago = condicionPago;
    }

    public MovimientoTienda getPedido() {
        return pedido;
    }

    public void setPedido(MovimientoTienda pedido) {
        this.pedido = pedido;
    }

    public Pool getPool() {
        return pool;
    }

    public void setPool(Pool pool) {
        this.pool = pool;
    }

    public UsuarioSessionBean getUsuarioSession() {
        return usuarioSession;
    }

    public void setUsuarioSession(UsuarioSessionBean usuarioSession) {
        this.usuarioSession = usuarioSession;
    }

    public ReservasPool getReserva() {
        return reserva;
    }

    public void setReserva(ReservasPool reserva) {
        this.reserva = reserva;
    }

    public boolean isSoloContado() {
        return soloContado;
    }

    public void setSoloContado(boolean soloContado) {
        this.soloContado = soloContado;
    }

    public List<CondicionesPagoPool> getCondicionesDisponibles() {
        return condicionesDisponibles;
    }

    public void setCondicionesDisponibles(List<CondicionesPagoPool> condicionesDisponibles) {
        this.condicionesDisponibles = condicionesDisponibles;
    }    

    public String getIdPool() {
        return idPool;
    }

    public void setIdPool(String idPool) {
        this.idPool = idPool;
    }
    
    private void asignarNroOrdenReserva() {
        
        int orden = pool.getReservas().size()+1;                 
        reserva.setOrden(orden);
        
        List<ItemReserva> itemsAux = reserva.getItemReservas();        
        reserva.setItemReservas(new ArrayList<ItemReserva>());
                
        for(ItemReserva ir: itemsAux){    
            
            if(ir.getCantidad().intValue()>0){
                
                ir.setOrden(orden);
                reserva.getItemReservas().add(ir);                
            }
        }        
        itemsAux.clear();
    }

    public PoolAplicacionBean getPoolAplicacionBean() {
        return poolAplicacionBean;
    }

    public void setPoolAplicacionBean(PoolAplicacionBean poolAplicacionBean) {
        this.poolAplicacionBean = poolAplicacionBean;
    }

    public MailFactory getMailFactoryBean() {
        return mailFactoryBean;
    }

    public void setMailFactoryBean(MailFactory mailFactoryBean) {
        this.mailFactoryBean = mailFactoryBean;
    }
}
